<template>
	<div
		:class="[
			'className' in item ? item.className(formData[item.prop]) : '',
			_fitContent ? 'fitContent' : '',
			_alignContent == 'center'
				? 'alignContent'
				: _alignContent == 'left'
				? 'leftContent'
				: _alignContent == 'right'
				? 'rightContent'
				: '',
			'itemContent',
		]">
		<template v-if="_type === 'empty'"></template>
		<template v-else-if="_type === 'dict'">
			<dict-tag :options="_dict" :value="formData[item.prop]" />
		</template>
		<template
			v-else-if="
				item.format && (formState === 'readonly' || !'type' in item || _type == 'text')
			">
			<TooltipDiv v-if="showOverflowTooltip" :content="item.format(formData)"></TooltipDiv>
			<div v-else class="textContent">
				{{ item.format(formData) | _setEmpty }}
			</div>
		</template>

		<template v-else-if="_type === 'select_dialog' && formState === 'readonly'">
			<TooltipDiv v-if="showOverflowTooltip" :content="formData[item.propLabel]"></TooltipDiv>
			<div v-else class="textContent">
				{{ formData[item.propLabel] | _setEmpty }}
			</div>
		</template>
		<template
			v-else-if="
				(_type === 'select' || _type === 'radioGroup' || _type === 'checkboxGroup') &&
				formState === 'readonly'
			">
			<TooltipDiv
				v-if="showOverflowTooltip"
				:content="
					computedSelectLabel(
						item.selectList || item.radioGroupList || item.checkboxGroupList,
						formData[item.prop],
					)
				"></TooltipDiv>
			<div v-else class="textContent">
				{{
					computedSelectLabel(
						item.selectList || item.radioGroupList || item.checkboxGroupList,
						formData[item.prop],
					) | _setEmpty
				}}
			</div>
		</template>
		<template v-else-if="_type === 'checkbox' && formState === 'readonly'">
			<TooltipDiv v-if="showOverflowTooltip" :content="getCheckboxLabel()"></TooltipDiv>
			<div v-else class="textContent">
				{{ getCheckboxLabel() | _setEmpty }}
			</div>
		</template>
		<!-- upload -->
		<template v-else-if="_type === 'upload'">
			<!-- <Upload -->
			<!-- ref="upload" -->
			<!-- :disabled="formState === 'disabled'" -->
			<!-- v-model="formData[item.prop]" -->
			<!-- v-bind="item.prototype" -->
			<!-- :size="item.size || 'small'" -->
			<!-- @[eventType]="eventCb(formData)" -->
			<!-- @uploadEnd="uploadEnd" -->
			<!-- > -->
			<!-- </Upload> -->
			<image-common
				v-model="formData[item.prop]"
				:disabled="formState === 'disabled' || formState === 'readonly'"
				:upType="2"
				v-bind="item.prototype"
				@uploadEnd="uploadEnd" />
		</template>
		<template v-else-if="(_type === 'price' || item.tag == 'price') && formState == 'readonly'">
			{{ format_thousand(formData[item.prop]) }}
		</template>
		<template
			v-else-if="
				(_type === 'text' || formState == 'readonly' || !'type' in item) &&
				item.tag !== 'readonlyEvent'
			">
			<TooltipDiv v-if="showOverflowTooltip" :content="formData[item.prop]"></TooltipDiv>
			<div v-else class="textContent">
				{{ formData[item.prop] | _setEmpty }}
			</div>
		</template>
		<template
			v-else-if="
				(_type === 'text' || formState == 'readonly' || !'type' in item) &&
				item.tag == 'readonlyEvent'
			">
			<div @[eventType]="eventCb(formData)" v-if="showOverflowTooltip" style="width: 100%">
				<TooltipDiv :content="formData[item.prop]"></TooltipDiv>
			</div>

			<div v-else class="textContent" @[eventType]="eventCb(formData)">
				{{ formData[item.prop] | _setEmpty }}
			</div>
		</template>
		<template v-else-if="_type === 'input'">
			<el-input
				:placeholder="placeholder"
				:disabled="formState === 'disabled'"
				v-bind="item.prototype"
				v-model="formData[item.prop]"
				clearable
				@[eventType]="eventCb(formData)"
				:size="item.size || 'small'"></el-input>
		</template>
		<!-- select -->

		<template v-else-if="_type === 'select' && !selectType">
			<el-select
				:placeholder="placeholder"
				:disabled="formState === 'disabled'"
				v-bind="item.prototype"
				v-model="formData[item.prop]"
				clearable
				filterable
				@[eventType]="eventCb(formData)"
				:size="item.size || 'small'">
				<el-option
					v-for="ele in _selectList"
					:key="item.array ? ele : ele[selectKey]"
					:label="item.array ? ele : ele[selectLabel]"
					:value="item.array ? ele : ele[selectValue]"
					:disabled="ele.disabled || ele[item.disabledProp]"></el-option>
			</el-select>
		</template>
		<!-- select -->
		<template v-else-if="_type === 'select' && selectType">
			<el-select
				:placeholder="placeholder"
				:disabled="formState === 'disabled'"
				v-bind="item.prototype"
				:value-key="item.valueKey"
				v-model="selectData"
				clearable
				filterable
				@[eventType]="eventCb(formData)"
				:size="item.size || 'small'">
				<el-option
					v-for="ele in _selectList"
					:key="item.array ? ele : ele[selectKey]"
					:label="item.array ? ele : ele[selectLabel]"
					:value="item.array ? ele : ele"
					:disabled="ele.disabled || ele[item.disabledProp]"></el-option>
			</el-select>
		</template>
		<!-- switch -->
		<template v-else-if="_type === 'switch'">
			<el-switch
				:disabled="formState === 'disabled'"
				v-bind="item.prototype"
				v-model="formData[item.prop]"
				active-color="#13ce66"
				inactive-color="#ff4949"
				@[eventType]="eventCb(formData)"
				:size="item.size || 'small'"></el-switch>
		</template>

		<!-- textarea -->
		<template v-else-if="_type === 'textarea'">
			<el-input
				:disabled="formState === 'disabled'"
				:autosize="{
					minRows: item.minRows || 3,
					maxRows: item.maxRows || 3,
				}"
				type="textarea"
				clearable
				:placeholder="placeholder"
				v-model="formData[item.prop]"
				:maxlength="item.maxlength"
				:resize="item.resize || 'none'"
				show-word-limit
				v-bind="item.prototype"
				@[eventType]="eventCb(formData)"
				:size="item.size || 'small'"></el-input>
		</template>
		<!-- select_dialog -->
		<template v-else-if="_type === 'select_dialog'">
			<el-input
				:disabled="formState === 'disabled'"
				:placeholder="placeholder"
				v-bind="item.prototype"
				v-model="formData[item.propLabel]"
				@focus="select_dialog(item, formData)"
				@clear="clear"
				ref="selectDialogInput"
				@[eventType]="eventCb(formData)"
				:size="item.size || 'small'"
				clearable></el-input>
		</template>
		<!-- datePicker -->
		<template v-else-if="_type === 'datePicker'">
			<el-date-picker
				v-model="formData[item.prop]"
				clearable
				:type="item.datePickerType || 'date'"
				:format="item.labelformat"
				:placeholder="placeholder"
				:disabled="formState === 'disabled'"
				:value-format="item.valueFormat || 'yyyy-MM-dd HH:mm:ss'"
				v-bind="item.prototype"
				:picker-options="pickerOptions(formData)"
				@[eventType]="eventCb(formData)"
				:size="item.size || 'small'"></el-date-picker>
		</template>
		<!-- radioGroup -->
		<template v-else-if="_type === 'radioGroup'">
			<el-radio-group v-model="formData[item.prop]" @[eventType]="eventCb(formData)">
				<el-radio
					v-for="ele in item.radioGroupList || []"
					:key="ele.value || ele.dictValue || ele[item.dictValue]"
					:label="ele.value || ele.dictValue || ele[item.dictValue]"
					:disabled="ele.disabled || formState === 'disabled'"
					v-bind="item.prototype">
					{{ ele.label || ele.dictLabel || ele[item.dictLabel] }}
				</el-radio>
			</el-radio-group>
		</template>
		<!-- checkbox -->
		<template v-else-if="_type === 'checkbox'">
			<el-checkbox
				v-model="formData[item.prop]"
				:disabled="formState === 'disabled' || formState === 'readonly'"
				v-bind="item.prototype"></el-checkbox>
		</template>
		<!-- checkboxGroup -->
		<template v-else-if="_type === 'checkboxGroup'">
			<el-checkbox-group @[eventType]="eventCb(formData)" v-model="formData[item.prop]">
				<el-checkbox
					v-for="ele in item.checkboxGroupList || []"
					:key="ele.value || ele[item.dictValue]"
					:label="ele.value || ele[item.dictValue]"
					:disabled="ele.disabled || formState === 'disabled'"
					v-bind="item.prototype">
					{{ ele.label || ele[item.dictLabel] }}
				</el-checkbox>
			</el-checkbox-group>
		</template>
		<template v-else-if="_type === 'input_number'">
			<el-input-number
				@[eventType]="eventCb(formData)"
				:placeholder="placeholder"
				:disabled="formState === 'disabled'"
				v-bind="item.prototype"
				v-model.number="formData[item.prop]"
				clearable
				step-strictly
				:min="item.min * 1 || 0"
				:max="item.max * 1 || Infinity"
				:size="item.size || 'small'"></el-input-number>
		</template>
		<template v-else-if="_type === 'price'">
			<el-input-number
				@[eventType]="eventCb(formData)"
				:placeholder="placeholder"
				:disabled="formState === 'disabled'"
				v-bind="item.prototype"
				v-model.number="formData[item.prop]"
				clearable
				step-strictly
				:min="item.min * 1 || 0"
				:max="item.max * 1 || Infinity"
				:size="item.size || 'small'"></el-input-number>
			<!-- <Price -->
			<!-- :placeholder="placeholder" -->
			<!-- :disabled="formState === 'disabled'" -->
			<!-- v-model="formData[item.prop]" -->
			<!-- clearable -->
			<!-- :min="_min" -->
			<!-- :max="_max" -->
			<!-- :size="item.size || 'small'" -->
			<!-- v-bind="item.prototype" -->
			<!-- :handleEvents="_handleEvents" -->
			<!-- :formData="formData" -->
			<!-- :index="index"></Price> -->
		</template>

		<template v-if="'slot' in item && notEmpty(item.slot)">
			<template v-for="(value, name) in _slot">
				<slot :name="value" v-if="hasOwnPrototype($slots, value)"></slot>
			</template>
			<template v-for="(value, name) in _slot">
				<slot
					:name="value"
					:row="formData || {}"
					:[`$index`]="index"
					v-if="hasOwnPrototype($scopedSlots, value)"></slot>
			</template>
		</template>
	</div>
</template>
<script>
	import Price from '../price/price.vue';
	import { listByIds } from '@/api/system/oss';
	import Upload from '@/components/FileUpload/pictureCard.vue';
	import TooltipDiv from '@/views/quota/forecast/chunk/tooltipDiv';
	export default {
		name: '',
		components: { Upload, TooltipDiv, Price },
		mixins: [],
		props: {
			value: {
				type: Object,
				default: () => ({}),
			},
			FormItem: {
				type: Object,
				default: () => {},
			},
			state: {
				required: false,
				type: String,
				default: 'write',
			},
			fitContent: {
				type: Boolean,
				default: false,
			},
			alignContent: {
				type: String,
			},
			index: {
				type: Number,
			},
			fromType: {
				required: false,
			},
		},
		data() {
			return {
				selectData: {},
			};
		},
		filters: {
			getSelectLabel(T, selectList, value) {
				if (!value) return '-';
				let values = '';
				if (typeof value == 'number') {
					values = value.toString().split(',');
				} else {
					values = value;
				}
				let word = '';
				if (selectList?.length > 0) {
					let items = selectList.filter(item => {
						return values.includes(item.value || item.dictValue);
					});
					word = items.reduce((prev, next) => {
						return `${prev}${prev ? '，' : ''}${next.label ?? next.dictLabel}`;
					}, word);
				}
				return word;
			},
			thousands(val) {
				if (this.Empty(val)) return '-';
				let price = Number(val);
				if (!Number.isFinite(price)) return '-';
				let fixed2 = (val * 1).toFixed(2);
				return !(fixed2 + '').includes('.')
					? // 就是说1-3位后面一定要匹配3位
					  (fixed2 + '').replace(/\d{1,3}(?=(\d{3})+$)/g, match => {
							return match + ',';
					  })
					: (fixed2 + '').replace(/\d{1,3}(?=(\d{3})+(\.))/g, match => {
							return match + ',';
					  });
				return new Intl.NumberFormat('en-us').format(price);
			},
		},
		watch: {
			selectData(val) {
				this.$set(this.formData, this.item.prop, val[this.selectValue]);
				this.$set(this.formData, this.item.propLabel, val[this.selectLabel]);
			},
			row: {
				deep: true,
				handler(val, oldVal) {
					this.item?.watch?.({ val, oldVal, row: this.formData });
				},
				immediate: false,
			},
		},
		computed: {
			pickerOptions() {
				return this.item?.pickerOptions ?? this.cb;
			},
			placeholder() {
				let message_type =
					this._type.includes('input') || this._type === 'textarea' ? '输入' : '选择';
				let message_label = this.item?.label?.replace(/(选择|输入)/g, '');
				let placeholder = `请${message_type}${message_label}`;
				return this.item.placeholder ?? placeholder ?? '请输入内容';
			},
			row() {
				return this.formData[this.item.prop];
			},
			item: {
				get() {
					return this.useVModel.call(this, this.FormItem, 'FormItem');
					// return this.FormItem;
				},
				set(val) {
					this.$emit('FormItem', val);
				},
			},
			formData: {
				get() {
					// return this.value;
					return this.useVModel.call(this);
				},
				set(val) {
					this.$emit('formData', val);
				},
			},
			_dict() {
				let dict = [];

				if (Object.prototype.toString.call(this.item.dict) == '[object Function]') {
					dict = this.item.dict(this.formData, this.index);
				} else {
					dict = this.item.dict;
				}
				return dict;
			},
			showOverflowTooltip() {
				let result = true;
				if (Reflect.has(this.item, 'showOverflowTooltip')) {
					result = this.item.showOverflowTooltip;
				} else {
					if (this.fromType == 'formItems') {
						result = false;
					} else if (this.fromType == 'tableCloumns') {
						result = true;
					}
				}
				return result;
			},
			selectLabel() {
				return this.item.selectLabel ?? this.item?.dictLabel ?? 'label';
			},
			selectValue() {
				return this.item.selectValue ?? this.item?.dictValue ?? 'value';
			},
			selectKey() {
				return (
					this.item.selectKey ?? this.item.selectValue ?? this.item?.dictValue ?? 'value'
				);
			},
			selectType() {
				return Reflect.has(this.item, 'propLabel');
			},
			_type() {
				let type = 'text';
				if (Object.prototype.toString.call(this.item.type) == '[object String]') {
					type = this.item.type;
				}
				if (Object.prototype.toString.call(this.item.type) == '[object Function]') {
					type = this.item.type(this.formData, this.index);
				}
				return type;
			},
			_fitContent() {
				return this.fitContent || this.item.fitContent;
			},
			_alignContent() {
				return this.alignContent || this.item.alignContent;
			},
			formState() {
				// return this?.item?.state ?? this.state;
				let state = 'disabled';

				if (Reflect.has(this.FormItem, 'show') && this.FormItem.show == false) {
					state = 'hidden';
				} else {
					if (typeof this.item.state == 'function') {
						state = this?.item?.state?.(this.formData, this.index);
					} else {
						state = this?.item?.state ?? this.state;
					}
				}
				return state;
			},
			eventType() {
				return this.FormItem?.event?.type ?? 'blur';
			},
			eventCb() {
				return this.FormItem?.event?.cb ?? this.cb;
			},
			_selectList() {
				if (Object.prototype.toString.call(this.item.selectList) == '[object Function]') {
					return this.item.selectList(this.formData, this.index);
				} else {
					return this.item.selectList;
				}
			},
			_min() {
				return Number.isFinite(this.item?.min * 1) ? this.item?.min * 1 : 0;
			},
			_max() {
				return Number.isFinite(this.item?.max * 1) ? this.item?.max * 1 : Infinity;
			},
			_slot() {
				if (this.Empty(this.item?.slot)) return [];
				let slots = this.item?.slot;
				if (typeof this.item.slot == 'function') {
					slots = this.item.slot({
						row: this.formData,
						index: this.index,
					});
				}
				if (typeof this.item.slot == 'string') {
					slots = this.item.slot.split(',');
				}
				return slots;
			},
			_handleEvents() {
				let events = {};
				if (Object.prototype.toString.call(this.item?.on) === '[object Object]') {
					for (const [key, value] of Object.entries(this.item.on)) {
						if (typeof value === 'function') {
							if (this.formState == 'write') {
								events[key] = value.bind(null, this.formData, this.index);
							}
						} else if (Object.prototype.toString.call(value) === '[object Object]') {
							let state = value.state ?? 'write';
							if (this.formState == state) {
								if (value.keepRaw === true) {
									events[key] = value.handler;
								} else {
									events[key] = value.handler.bind(
										null,
										this.formData,
										this.index,
									);
								}
							}
						}
					}
				}
				if ('event' in this.item) {
					events[this.item.event?.type] = this.item.event.cb.bind(null, this.formData);
				}
				return events;
			},
		},
		created() {
			if (this.formData[this.item.prop] === null) {
				this.formData[this.item.prop] = undefined;
			}
		},
		mounted() {},
		beforeDestroy() {},
		methods: {
			valid() {
				return new Promise(async resolve => {
					let result = true;
					let refs = Object.values(this.$refs);
					for (let index = 0; index < refs?.length; index++) {
						const ref = refs[index];
						if (Object.prototype.toString.call(ref) == '[object Array]') {
							for (let i = 0; i < ref.length; i++) {
								const element = ref[i];
								if (element?.valid) {
									let rc = await element?.valid?.();
									result = result && rc;
								}
								if (element?.validate) {
									let rf = await this._valid(ref);
									result = result && rf;
								}
								if (element?.form_validate) {
									let rf = await this._valid(ref, 'form_validate');
									result = result && rf;
								}
							}
						} else {
							if (ref?.valid) {
								let rc = await ref?.valid?.();
								result = result && rc;
							}
							if (ref?.validate) {
								let rf = await this._valid(ref);
								result = result && rf;
							}
							if (ref?.form_validate) {
								let rf = await this._valid(ref, 'form_validate');
								result = result && rf;
							}
						}
					}

					resolve(result);
				});
			},
			hasOwnPrototype(obj, key) {
				if (typeof obj !== 'object') return;
				return Reflect.has(obj, key);
			},
			uploadEnd(result) {
				this.item?.uploadEnd?.(result);
			},
			getCheckboxLabel() {
				let key = this.formData[this.item.prop];
				if (key == true) {
					return this.item.prototype.trueLabel ?? '是';
				} else if (key == false) {
					return this.item.prototype.falseLabel ?? '否';
				} else {
					return '-';
				}
			},
			computedSelectLabel(selectList, value) {
				if (this.Empty(value)) return '-';
				let values = '';
				if (Object.prototype.toString.call(value) == '[object Array]') {
					values = value;
				} else if (value?.includes?.(',')) {
					values = value.toString().split(',');
				} else {
					values = [value?.toString()];
				}
				let word = undefined;
				let arr = [];
				if (Object.prototype.toString.call(selectList) == '[object Function]') {
					arr = selectList(this.formData, this.index);
				}
				if (Object.prototype.toString.call(selectList) == '[object Array]') {
					arr = selectList;
				}
				if (arr?.length > 0) {
					if (this.item.array) {
						let items = arr.filter(e => {
							return values.includes(e);
						});
						word = items.reduce((prev, next) => {
							return `${prev ? prev : ''}${prev ? '，' : ''}${next}`;
						}, word);
					} else {
						let items = arr.filter(e => {
							return values.includes(
								e[this.selectValue]?.toString() || e.dictValue?.toString(),
							);
						});
						word = items.reduce((prev, next) => {
							return `${prev ? prev : ''}${prev ? '，' : ''}${
								next[this.selectLabel] ?? next.dictLabel
							}`;
						}, word);
					}
				}
				if (this.item?.showDictValue === true || !('showDictValue' in this.item)) {
					return word ?? value ?? '-';
				} else {
					return word ?? '-';
				}
			},
			cb() {},
			select_dialog(item, row) {
				if ('selectDialogValidate' in item) {
					if (!item.selectDialogValidate()) return;
				}
				this.$refs.selectDialogInput.blur();
				this.$SelectDialog(item.selectDialogParams).then(({ res, type }) => {
					item?.cb(res, row, this.index, type);
				});
			},
			clear() {
				this.formData[this.item.prop] = undefined;
				this.formData[this.item.propLabel] = undefined;
				this.item?.cb({}, this.formData, undefined, undefined);
			},
		},
	};
</script>
<style lang="scss" scoped>
	.itemContent {
		--maxWidth: 300px;
		::v-deep .el-date-editor {
			width: 100%;
			max-width: var(--maxWidth);
		}

		::v-deep .el-input {
			width: 100%;
			max-width: var(--maxWidth);
		}
		::v-deep .el-select {
			width: 100%;
			max-width: var(--maxWidth);
		}
		::v-deep .el-textarea {
			width: 100%;
			max-width: var(--maxWidth);
		}
		::v-deep .el-input-number {
			width: 100%;
			max-width: var(--maxWidth);
			.el-input-number__decrease,
			.el-input-number__increase {
				display: none;
			}
			input {
				padding: 5px;
				text-align: left;
				width: 100%;
				max-width: var(--maxWidth);
			}
		}
	}
	.itemContent.fitContent {
		::v-deep .el-date-editor {
			width: 100%;
			max-width: none;
		}
		::v-deep .el-input {
			width: 100%;
			max-width: none;
		}
		::v-deep .el-select {
			width: 100%;
			max-width: none;
		}
		::v-deep .el-textarea {
			width: 100%;
			max-width: none;
		}
		::v-deep .el-input-number {
			width: 100%;
			max-width: none;
			.el-input-number__decrease,
			.el-input-number__increase {
				display: none;
			}
			input {
				padding: 5px;
				text-align: left;
				width: 100%;
				max-width: none;
			}
		}
	}
	.itemContent.alignContent {
		justify-content: center;
	}

	.itemContent {
		display: flex;
	}
	::v-deep div:empty::before {
		content: '-';
	}
	.textContent {
		overflow-wrap: break-word;
		word-wrap: break-word;
		word-break: break-all;
	}
	::v-deep .el-radio {
		line-height: 32px;
	}
</style>
